{"componentChunkName":"component---src-templates-blog-post-blog-post-js","path":"/articulos/view-transitions-api-aplicaciones-web/","result":{"data":{"mdx":{"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"View Transitions API: cómo crear aplicaciones web con transiciones nativas sin depender de un framework\",\n  \"seoTitle\": \"View Transitions API: transiciones nativas para SPA y MPA\",\n  \"slug\": \"view-transitions-api-aplicaciones-web\",\n  \"description\": \"Aprende a utilizar View Transitions API para crear transiciones fluidas en aplicaciones SPA y multipágina. Ejemplos prácticos con JavaScript y CSS, compatibilidad y cuándo merece la pena usarla.\",\n  \"description_sort\": \"Cómo usar View Transitions API en SPA y MPA con JavaScript y CSS\",\n  \"date\": \"2026-09-07\",\n  \"category\": \"JavaScript\",\n  \"featuredImage\": \"view-transitions-api-portada.webp\",\n  \"twitterUsername\": \"@CursosDesarrol1\",\n  \"tags\": [\"javascript\", \"css\", \"view-transitions\", \"desarrollo-web\", \"spa\", \"mpa\"]\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"span\", {\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1200px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/458bb892895d6fa1021e36b3fe615b65/a8642/view-transitions-api-portada.webp\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"66.66666666666666%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/webp;base64,UklGRooAAABXRUJQVlA4IH4AAADwAwCdASoUAA0APtFUo0uoJKMhsAgBABoJQBfnBER+2i8wM3RT8+/AAP7yK9RR4IEH5RiXVH5woLUcJYyUDOCJOR9NFp7UkGN76Hf9z2RcQ1H66BUouE7VXX2+AviXAuzPJ4dw74I2dlgP95mtyMcTxBC8KPK64uk3Dwo3oAA=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"Pantalla de un ordenador que muestra una transición fluida entre una tarjeta de producto y su página de detalle\",\n    \"title\": \"Pantalla de un ordenador que muestra una transición fluida entre una tarjeta de producto y su página de detalle\",\n    \"src\": \"/static/458bb892895d6fa1021e36b3fe615b65/5bb53/view-transitions-api-portada.webp\",\n    \"srcSet\": [\"/static/458bb892895d6fa1021e36b3fe615b65/cb58d/view-transitions-api-portada.webp 300w\", \"/static/458bb892895d6fa1021e36b3fe615b65/f8b1b/view-transitions-api-portada.webp 600w\", \"/static/458bb892895d6fa1021e36b3fe615b65/5bb53/view-transitions-api-portada.webp 1200w\", \"/static/458bb892895d6fa1021e36b3fe615b65/a8642/view-transitions-api-portada.webp 1536w\"],\n    \"sizes\": \"(max-width: 1200px) 100vw, 1200px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), mdx(\"br\", null), mdx(\"br\", null), mdx(\"h1\", null, \"View Transitions API: c\\xF3mo crear aplicaciones web con transiciones nativas sin depender de un framework\"), mdx(\"p\", null, \"Durante a\\xF1os, una de las principales ventajas visuales de las aplicaciones de una sola p\\xE1gina, conocidas como SPA, ha sido su capacidad para cambiar de pantalla sin recargar completamente el documento. Frameworks como React, Angular o Vue permiten mantener el estado de la aplicaci\\xF3n y construir experiencias fluidas, pero tambi\\xE9n han contribuido a que asociemos las transiciones modernas con arquitecturas cada vez m\\xE1s complejas.\"), mdx(\"p\", null, \"La plataforma web est\\xE1 cambiando esa situaci\\xF3n. View Transitions API permite al navegador animar los cambios entre dos estados visuales, tanto dentro de un mismo documento como durante determinadas navegaciones entre p\\xE1ginas HTML diferentes. Esto significa que una aplicaci\\xF3n multip\\xE1gina puede ofrecer transiciones similares a las de una SPA sin tener que convertir toda su navegaci\\xF3n en un sistema JavaScript.\"), mdx(\"p\", null, \"En este art\\xEDculo vamos a analizar c\\xF3mo funciona esta API, por qu\\xE9 es relevante para el desarrollo web actual y c\\xF3mo incorporarla a una aplicaci\\xF3n real con ejemplos de JavaScript y CSS.\"), mdx(\"h2\", null, \"Por qu\\xE9 View Transitions vuelve a ser un tema de actualidad\"), mdx(\"p\", null, \"La API no apareci\\xF3 en 2026. Chrome incorpor\\xF3 las transiciones dentro de un mismo documento en 2023 y ampli\\xF3 el soporte a navegaciones entre documentos en 2024. Sin embargo, durante 2025 y 2026 se han producido avances relevantes en compatibilidad y funcionalidades, incluido el soporte de transiciones dentro de un documento en Firefox 144 y la incorporaci\\xF3n de \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"waitUntil()\"), \" en Chrome 144.\"), mdx(\"p\", null, \"La importancia de esta evoluci\\xF3n no est\\xE1 en una nueva animaci\\xF3n, sino en que los navegadores est\\xE1n asumiendo una responsabilidad que antes sol\\xEDamos resolver mediante bibliotecas, routers y bastante c\\xF3digo de coordinaci\\xF3n.\"), mdx(\"p\", null, \"Esto encaja con una tendencia m\\xE1s amplia del desarrollo web: aprovechar capacidades nativas antes de introducir dependencias para resolver problemas que el navegador ya puede gestionar.\"), mdx(\"h2\", null, \"Qu\\xE9 es View Transitions API\"), mdx(\"p\", null, \"View Transitions API es una interfaz de la plataforma web que permite crear una transici\\xF3n visual entre un estado anterior y uno nuevo. En lugar de obligarnos a calcular manualmente las posiciones de los elementos, el navegador captura los estados necesarios y genera una animaci\\xF3n basada en CSS.\"), mdx(\"p\", null, \"El proceso, simplificado, es el siguiente:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"El navegador captura el estado visual anterior.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Se actualiza el DOM o se realiza la navegaci\\xF3n.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Se captura el estado visual nuevo.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"El navegador anima la transici\\xF3n entre ambos estados.\")), mdx(\"p\", null, \"La API utiliza seudoelementos CSS espec\\xEDficos, como \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"::view-transition-old()\"), \" y \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"::view-transition-new()\"), \", para representar las im\\xE1genes del estado anterior y del nuevo durante la animaci\\xF3n.\"), mdx(\"p\", null, \"Lo interesante es que existen dos formas principales de utilizarla: dentro de un mismo documento y entre documentos diferentes.\"), mdx(\"h2\", null, \"Transiciones en una SPA: actualizar el DOM sin un salto visual\"), mdx(\"p\", null, \"Imaginemos una aplicaci\\xF3n que muestra una lista de productos. Al seleccionar uno, queremos sustituir la lista por una vista de detalle sin que el cambio resulte brusco. Una implementaci\\xF3n tradicional puede utilizar animaciones CSS, controlar cu\\xE1ndo se desmontan los componentes y coordinar el estado de entrada y salida.\"), mdx(\"p\", null, \"Con View Transitions podemos delegar parte de esa coordinaci\\xF3n en el navegador.\"), mdx(\"h3\", null, \"Un ejemplo b\\xE1sico con JavaScript\"), mdx(\"p\", null, \"Supongamos que tenemos este HTML:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, '<main id=\"app\">\\n  <section class=\"product-list\">\\n    <h1>Productos</h1>\\n    <button id=\"show-detail\">Ver producto</button>\\n  </section>\\n</main>'), mdx(\"p\", null, \"Y queremos sustituir el contenido al pulsar el bot\\xF3n:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, 'const app = document.querySelector(\"#app\")\\n\\nfunction showProductDetail() {\\n  app.innerHTML = \"<section class=\\\\\"product-detail\\\\\">\" +\\n    \"<h1>Ordenador portátil</h1>\" +\\n    \"<p>Información detallada del producto.</p>\" +\\n    \"<button id=\\\\\"back\\\\\">Volver</button>\" +\\n    \"</section>\"\\n\\n  document.querySelector(\"#back\").addEventListener(\"click\", () => {\\n    window.location.reload()\\n  })\\n}\\n\\ndocument.querySelector(\"#show-detail\").addEventListener(\"click\", () => {\\n  if (!document.startViewTransition) {\\n    showProductDetail()\\n    return\\n  }\\n\\n  document.startViewTransition(() => {\\n    showProductDetail()\\n  })\\n})'), mdx(\"p\", null, \"El ejemplo es deliberadamente sencillo: no utiliza ning\\xFAn framework ni gestiona un router. La llamada a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"document.startViewTransition()\"), \" recibe una funci\\xF3n encargada de actualizar el DOM. El navegador captura el estado anterior, ejecuta esa actualizaci\\xF3n y prepara la transici\\xF3n hacia el nuevo estado.\"), mdx(\"p\", null, \"Si el navegador no soporta la API, el contenido se actualiza igualmente. Esta degradaci\\xF3n progresiva es importante: la animaci\\xF3n debe mejorar la experiencia, no convertirse en un requisito para utilizar la aplicaci\\xF3n.\"), mdx(\"p\", null, \"En una aplicaci\\xF3n real, la funci\\xF3n de actualizaci\\xF3n ser\\xEDa sustituida por el renderizado del framework, un cambio de estado o la navegaci\\xF3n del router.\"), mdx(\"h2\", null, \"Personalizar la animaci\\xF3n con CSS\"), mdx(\"p\", null, \"Por defecto, el navegador aplica una transici\\xF3n de fundido entre los estados. Podemos modificarla utilizando los seudoelementos de View Transitions.\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, '::view-transition-old(root) {\\n  animation: 150ms ease-in both fade-out;\\n}\\n\\n::view-transition-new(root) {\\n  animation: 250ms ease-out both fade-in;\\n}\\n\\n@keyframes fade-out {\\n  to {\\n    opacity: 0;\\n  }\\n}\\n\\n@keyframes fade-in {\\n  from {\\n    opacity: 0;\\n  }\\n}'), mdx(\"p\", null, \"El nombre \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"root\"), \" hace referencia a la transici\\xF3n del documento completo. Esto resulta \\xFAtil para cambios sencillos de pantalla, pero la API tambi\\xE9n permite identificar elementos concretos para que el navegador anime su transformaci\\xF3n entre dos vistas.\"), mdx(\"h2\", null, \"Animar un elemento compartido: de tarjeta a detalle\"), mdx(\"p\", null, \"Uno de los usos m\\xE1s interesantes es la transici\\xF3n de un elemento compartido. Por ejemplo, una imagen de producto que aparece en una tarjeta y despu\\xE9s ocupa una posici\\xF3n mayor en la p\\xE1gina de detalle.\"), mdx(\"span\", {\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1200px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/f06b1e096525a67117fb58edf0ac5ace/a8642/view-transitions-elemento-compartido.webp\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"66.66666666666666%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/webp;base64,UklGRlQAAABXRUJQVlA4IEgAAACwAwCdASoUAA0APtFUpEuoJKOhsAgBABoJaQAAW+mQ/n/ccqmSAAD+9M7IglQFsPOU9r8ucSJitP48c/buIfj5d9jdOweAAAA=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"Dos interfaces de producto conectadas por una transición de elemento compartido entre tarjeta y detalle\",\n    \"title\": \"Dos interfaces de producto conectadas por una transición de elemento compartido entre tarjeta y detalle\",\n    \"src\": \"/static/f06b1e096525a67117fb58edf0ac5ace/5bb53/view-transitions-elemento-compartido.webp\",\n    \"srcSet\": [\"/static/f06b1e096525a67117fb58edf0ac5ace/cb58d/view-transitions-elemento-compartido.webp 300w\", \"/static/f06b1e096525a67117fb58edf0ac5ace/f8b1b/view-transitions-elemento-compartido.webp 600w\", \"/static/f06b1e096525a67117fb58edf0ac5ace/5bb53/view-transitions-elemento-compartido.webp 1200w\", \"/static/f06b1e096525a67117fb58edf0ac5ace/a8642/view-transitions-elemento-compartido.webp 1536w\"],\n    \"sizes\": \"(max-width: 1200px) 100vw, 1200px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), mdx(\"p\", null, \"Para conseguirlo, asignamos el mismo \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"view-transition-name\"), \" al elemento correspondiente en ambos estados:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, '.product-image {\\n  view-transition-name: product-image;\\n}'), mdx(\"p\", null, \"En la vista de listado:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, '<img\\n  class=\"product-image\"\\n  src=\"/images/portatil.jpg\"\\n  alt=\"Ordenador portátil\"\\n/>'), mdx(\"p\", null, \"Y en la vista de detalle:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, '<img\\n  class=\"product-image\"\\n  src=\"/images/portatil.jpg\"\\n  alt=\"Ordenador portátil\"\\n/>'), mdx(\"p\", null, \"El navegador puede relacionar ambos elementos y animar el cambio de tama\\xF1o y posici\\xF3n. No necesitamos calcular las coordenadas de origen y destino ni mantener dos elementos superpuestos mediante JavaScript.\"), mdx(\"p\", null, \"Hay una condici\\xF3n importante: los nombres deben ser \\xFAnicos dentro del \\xE1mbito de cada transici\\xF3n. Si varias tarjetas visibles comparten el mismo nombre, podemos provocar que la transici\\xF3n no se ejecute correctamente. Para listas din\\xE1micas conviene asignar el nombre \\xFAnicamente al elemento seleccionado o utilizar estrategias de nombres \\xFAnicos.\"), mdx(\"h2\", null, \"La diferencia decisiva: transiciones entre p\\xE1ginas HTML\"), mdx(\"p\", null, \"Hasta aqu\\xED seguimos trabajando dentro de un mismo documento, algo habitual en una SPA. La parte que realmente cambia el planteamiento arquitect\\xF3nico es la posibilidad de animar navegaciones entre documentos.\"), mdx(\"p\", null, \"Imaginemos una web construida con Astro, una aplicaci\\xF3n renderizada en servidor o incluso p\\xE1ginas HTML tradicionales. Cada enlace carga un documento nuevo desde el servidor. Antes, conseguir una transici\\xF3n coordinada entre ambas p\\xE1ginas requer\\xEDa interceptar la navegaci\\xF3n y construir una capa JavaScript adicional.\"), mdx(\"p\", null, \"Ahora podemos habilitar transiciones entre documentos del mismo origen con una regla CSS:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, '@view-transition {\\n  navigation: auto;\\n}'), mdx(\"p\", null, \"Esta regla debe estar presente en las dos p\\xE1ginas participantes. Cuando se produce una navegaci\\xF3n compatible, el navegador puede realizar autom\\xE1ticamente la transici\\xF3n.\"), mdx(\"p\", null, \"Por ejemplo:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, '<a href=\"/productos/portatil/\">Ver detalles</a>'), mdx(\"p\", null, \"No hay que sustituir el enlace por un bot\\xF3n ni interceptar el clic con JavaScript. El enlace contin\\xFAa siendo una navegaci\\xF3n HTML normal.\"), mdx(\"h3\", null, \"Ejemplo de estructura multip\\xE1gina\"), mdx(\"p\", null, \"Podr\\xEDamos tener una aplicaci\\xF3n con esta estructura:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, 'public/\\n├── index.html\\n├── productos/\\n│   ├── index.html\\n│   └── portatil.html\\n└── styles.css'), mdx(\"p\", null, \"Tanto la p\\xE1gina de listado como la de detalle cargar\\xEDan el mismo CSS:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, '@view-transition {\\n  navigation: auto;\\n}\\n\\n.product-image {\\n  view-transition-name: product-image;\\n}\\n\\n::view-transition-old(root) {\\n  animation-duration: 150ms;\\n}\\n\\n::view-transition-new(root) {\\n  animation-duration: 250ms;\\n}'), mdx(\"p\", null, \"La navegaci\\xF3n sigue funcionando aunque el navegador no soporte la transici\\xF3n. Esta es una ventaja de utilizar enlaces reales y mantener la funcionalidad independiente del efecto visual.\"), mdx(\"span\", {\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1200px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/9da69f182a0ef1ac27947af338531a9d/a8642/view-transitions-api-spa-mpa.webp\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"66.66666666666666%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/webp;base64,UklGRoAAAABXRUJQVlA4IHQAAADQAwCdASoUAA0APtFUo0uoJKMhsAgBABoJYwC7ACP7thiDJSsvKwAA/rgfsK3V/+Mn+zuYwsudT4sYBLy+2rgje2ujjT5pPR9oo7rBrYGAKwV63uXXs+sb5kxTTdX+XB3QBmLBzigaOwMbKGOX+8R0VAAAAA==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"Comparación visual de navegación con transición dentro de una SPA y entre páginas HTML de una MPA\",\n    \"title\": \"Comparación visual de navegación con transición dentro de una SPA y entre páginas HTML de una MPA\",\n    \"src\": \"/static/9da69f182a0ef1ac27947af338531a9d/5bb53/view-transitions-api-spa-mpa.webp\",\n    \"srcSet\": [\"/static/9da69f182a0ef1ac27947af338531a9d/cb58d/view-transitions-api-spa-mpa.webp 300w\", \"/static/9da69f182a0ef1ac27947af338531a9d/f8b1b/view-transitions-api-spa-mpa.webp 600w\", \"/static/9da69f182a0ef1ac27947af338531a9d/5bb53/view-transitions-api-spa-mpa.webp 1200w\", \"/static/9da69f182a0ef1ac27947af338531a9d/a8642/view-transitions-api-spa-mpa.webp 1536w\"],\n    \"sizes\": \"(max-width: 1200px) 100vw, 1200px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n  \"), \"\\n    \"), mdx(\"h3\", null, \"Las limitaciones que conviene conocer\"), mdx(\"p\", null, \"Las transiciones entre documentos tienen requisitos y limitaciones. En particular, deben producirse entre documentos del mismo origen y ambos deben habilitar la funcionalidad. No se aplican a cualquier navegaci\\xF3n externa ni sustituyen el comportamiento habitual de todos los enlaces del navegador.\"), mdx(\"p\", null, \"Tampoco debemos asumir que todas las funcionalidades avanzadas est\\xE1n disponibles en todos los navegadores. El soporte de las transiciones dentro de un documento y el de las transiciones entre documentos no es exactamente el mismo. Antes de utilizar caracter\\xEDsticas avanzadas en producci\\xF3n, es necesario consultar las tablas de compatibilidad y probar los navegadores que realmente utilizan nuestros usuarios.\"), mdx(\"h2\", null, \"\\xBFSignifica esto que las SPA dejan de tener sentido?\"), mdx(\"p\", null, \"No. Ser\\xEDa una conclusi\\xF3n equivocada.\"), mdx(\"p\", null, \"Una SPA no existe \\xFAnicamente para animar cambios de pantalla. Tambi\\xE9n permite mantener estado en memoria, gestionar interacciones complejas, evitar determinadas recargas, coordinar m\\xFAltiples componentes y construir interfaces que se comportan como una aplicaci\\xF3n de escritorio.\"), mdx(\"p\", null, \"View Transitions resuelve un problema visual y de coordinaci\\xF3n de estados, pero no sustituye una arquitectura de aplicaci\\xF3n.\"), mdx(\"p\", null, \"La diferencia es que ahora tenemos una raz\\xF3n menos para elegir una SPA cuando lo que realmente necesitamos es una web de contenido, un cat\\xE1logo, una documentaci\\xF3n o una aplicaci\\xF3n con navegaci\\xF3n relativamente sencilla.\"), mdx(\"p\", null, \"Una MPA puede seguir ofreciendo ventajas como HTML generado en servidor, menor dependencia de JavaScript para la navegaci\\xF3n y una arquitectura m\\xE1s simple. View Transitions permite mejorar su experiencia visual sin renunciar a esas caracter\\xEDsticas.\"), mdx(\"h2\", null, \"C\\xF3mo encaja con React, Angular y otros frameworks\"), mdx(\"p\", null, \"La API es nativa, pero eso no significa que debamos dejar de utilizar frameworks. Su papel es complementario.\"), mdx(\"p\", null, \"En React, por ejemplo, puede utilizarse para coordinar cambios visuales asociados al estado o al router. En Angular, una navegaci\\xF3n o una actualizaci\\xF3n de componentes puede beneficiarse de las capacidades nativas cuando la integraci\\xF3n del framework y del navegador lo permita. Frameworks orientados a contenido, como Astro, tambi\\xE9n pueden aprovechar las transiciones entre documentos o proporcionar integraciones espec\\xEDficas.\"), mdx(\"p\", null, \"Lo importante es separar responsabilidades. El framework gestiona componentes, estado y l\\xF3gica de aplicaci\\xF3n; el navegador puede encargarse de parte de la transici\\xF3n visual. As\\xED evitamos introducir una biblioteca de animaci\\xF3n completa cuando \\xFAnicamente necesitamos animar un cambio de vista.\"), mdx(\"p\", null, \"No obstante, para animaciones complejas, secuencias cinematogr\\xE1ficas, f\\xEDsicas, gestos avanzados o interacciones con control preciso de la l\\xEDnea temporal, herramientas especializadas como GSAP pueden seguir siendo m\\xE1s adecuadas.\"), mdx(\"h2\", null, \"Accesibilidad: no todos los usuarios quieren animaciones\"), mdx(\"p\", null, \"Una transici\\xF3n visual no debe perjudicar a quienes prefieren reducir el movimiento. El navegador expone esta preferencia mediante la media query \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prefers-reduced-motion\"), \".\"), mdx(\"p\", null, \"Podemos utilizarla para desactivar las animaciones de View Transitions:\"), mdx(CodeJs, {\n    mdxType: \"CodeJs\"\n  }, '@media (prefers-reduced-motion: reduce) {\\n  ::view-transition-old(root),\\n  ::view-transition-new(root) {\\n    animation-duration: 0.01ms;\\n  }\\n}'), mdx(\"p\", null, \"En una aplicaci\\xF3n real tambi\\xE9n conviene revisar los elementos animados individualmente, especialmente cuando hay desplazamientos grandes, zoom o efectos que pueden resultar molestos.\"), mdx(\"p\", null, \"La accesibilidad no consiste \\xFAnicamente en ofrecer una alternativa cuando la API no est\\xE1 soportada. Tambi\\xE9n implica respetar las preferencias del sistema y evitar que una mejora est\\xE9tica dificulte el uso de la interfaz.\"), mdx(\"h2\", null, \"Cu\\xE1ndo merece la pena utilizar View Transitions\"), mdx(\"p\", null, \"La API resulta especialmente interesante en aplicaciones donde existe una relaci\\xF3n visual clara entre dos estados: una tarjeta que se convierte en detalle, un listado que cambia de orden, una galer\\xEDa, una navegaci\\xF3n entre secciones o un panel que se abre y se cierra.\"), mdx(\"p\", null, \"Tambi\\xE9n puede ser \\xFAtil en webs multip\\xE1gina que quieren mejorar la sensaci\\xF3n de continuidad sin incorporar un sistema de navegaci\\xF3n cliente.\"), mdx(\"p\", null, \"En cambio, no tiene demasiado sentido introducir transiciones en todos los cambios de estado por el simple hecho de que sea posible. Las animaciones excesivas pueden ralentizar la percepci\\xF3n de la interfaz, distraer y hacer que una aplicaci\\xF3n de gesti\\xF3n resulte menos eficiente.\"), mdx(\"p\", null, \"Para aplicaciones empresariales, la prioridad suele ser que las acciones sean r\\xE1pidas, previsibles y claras. Una transici\\xF3n breve puede ayudar a comprender un cambio de contexto, pero una animaci\\xF3n larga cada vez que se abre un formulario probablemente empeorar\\xE1 la experiencia.\"), mdx(\"h2\", null, \"Qu\\xE9 aporta realmente al desarrollo web moderno\"), mdx(\"p\", null, \"View Transitions es un ejemplo de c\\xF3mo la plataforma web contin\\xFAa incorporando capacidades que antes depend\\xEDan de soluciones externas. No elimina la necesidad de frameworks ni convierte las aplicaciones tradicionales en obsoletas, pero ampl\\xEDa las opciones disponibles.\"), mdx(\"p\", null, \"El desarrollador puede elegir una arquitectura SPA, MPA o h\\xEDbrida por sus necesidades reales de estado, renderizado, SEO y mantenimiento, en lugar de hacerlo \\xFAnicamente por la experiencia visual que desea conseguir.\"), mdx(\"p\", null, \"Ese es el cambio importante: las transiciones dejan de ser una caracter\\xEDstica asociada a una arquitectura concreta y pasan a formar parte de las capacidades del navegador.\"), mdx(\"h2\", null, \"Conclusi\\xF3n\"), mdx(\"p\", null, \"La evoluci\\xF3n de View Transitions API demuestra que no todas las mejoras del desarrollo web llegan mediante nuevos frameworks o herramientas de inteligencia artificial. A veces, la innovaci\\xF3n consiste en trasladar una responsabilidad al navegador y simplificar el c\\xF3digo que necesitamos mantener.\"), mdx(\"p\", null, \"Para proyectos nuevos, merece la pena conocer esta API antes de incorporar dependencias de animaci\\xF3n. Para proyectos existentes, puede ser una oportunidad de mejorar determinadas interacciones sin modificar toda la arquitectura.\"), mdx(\"p\", null, \"La recomendaci\\xF3n es utilizarla de forma progresiva: comenzar con transiciones sencillas, comprobar la compatibilidad de las funcionalidades necesarias y mantener siempre la navegaci\\xF3n y los cambios de estado operativos sin animaci\\xF3n.\"), mdx(\"p\", null, \"El objetivo no es que una web tenga m\\xE1s movimiento, sino que el usuario comprenda mejor lo que est\\xE1 ocurriendo mientras la aplicaci\\xF3n sigue siendo r\\xE1pida, accesible y mantenible.\"), mdx(\"h2\", null, \"Referencias y documentaci\\xF3n\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API\"\n  }, \"View Transition API - MDN\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API/Using\"\n  }, \"Using the View Transition API - MDN\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://developer.chrome.com/docs/web-platform/view-transitions\"\n  }, \"View Transitions - Chrome for Developers\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://developer.chrome.com/blog/view-transitions-in-2025\"\n  }, \"What's new in view transitions (2025 update)\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://developer.chrome.com/release-notes/144\"\n  }, \"Chrome 144 release notes\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://caniuse.com/view-transitions\"\n  }, \"Compatibilidad de transiciones dentro de un documento\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://caniuse.com/cross-document-view-transitions\"\n  }, \"Compatibilidad de transiciones entre documentos\"))));\n}\n;\nMDXContent.isMDXComponent = true;","frontmatter":{"twitterUsername":"@CursosDesarrol1","title":"View Transitions API: cómo crear aplicaciones web con transiciones nativas sin depender de un framework","seoTitle":"View Transitions API: transiciones nativas para SPA y MPA","date":"2026-09-07","description":"Aprende a utilizar View Transitions API para crear transiciones fluidas en aplicaciones SPA y multipágina. Ejemplos prácticos con JavaScript y CSS, compatibilidad y cuándo merece la pena usarla.","featuredImage":{"childImageSharp":{"fluid":{"base64":"data:image/webp;base64,UklGRooAAABXRUJQVlA4IH4AAADwAwCdASoUAA0APtFUo0uoJKMhsAgBABoJQBfnBER+2i8wM3RT8+/AAP7yK9RR4IEH5RiXVH5woLUcJYyUDOCJOR9NFp7UkGN76Hf9z2RcQ1H66BUouE7VXX2+AviXAuzPJ4dw74I2dlgP95mtyMcTxBC8KPK64uk3Dwo3oAA=","aspectRatio":1.5037593984962405,"src":"/static/458bb892895d6fa1021e36b3fe615b65/ccdb5/view-transitions-api-portada.webp","srcSet":"/static/458bb892895d6fa1021e36b3fe615b65/6b183/view-transitions-api-portada.webp 200w,\n/static/458bb892895d6fa1021e36b3fe615b65/fc32b/view-transitions-api-portada.webp 400w,\n/static/458bb892895d6fa1021e36b3fe615b65/ccdb5/view-transitions-api-portada.webp 800w,\n/static/458bb892895d6fa1021e36b3fe615b65/9000d/view-transitions-api-portada.webp 1200w,\n/static/458bb892895d6fa1021e36b3fe615b65/7dd62/view-transitions-api-portada.webp 1536w","sizes":"(max-width: 800px) 100vw, 800px"}}}}}},"pageContext":{"slug":"/articulos/view-transitions-api-aplicaciones-web/","previous":{"fields":{"slug":"/avisos_legales/politica_cookies/"}},"next":null}},"staticQueryHashes":["2032873950"]}